package stendcontrol;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

public class UdpServer extends TransmitExp implements Runnable {

    //работа потока
    protected boolean thread_runing = true;
    protected DatagramSocket dsocket;
    protected DatagramPacket dinpacket;
    protected DatagramPacket doutpacket;
    protected byte[] rbuffer = new byte[1521];
    protected byte[] tbuffer = new byte[1];
    protected int in_port;
    protected int out_port;
    protected byte[] out_addr;
    
    public UdpServer(byte[] out_addr, int in_port, int out_port)
            throws SocketException, UnknownHostException {

        //для проверки приходящих пакетов на корректность порта
        this.in_port = in_port;
        this.out_port = out_port;
        //проверка на IP
        this.out_addr = out_addr;

        dsocket = new DatagramSocket(in_port);
        dsocket.setSoTimeout(1000);
        dsocket.setBroadcast(true);

        dinpacket = new DatagramPacket(rbuffer, rbuffer.length);

        doutpacket = new DatagramPacket(tbuffer, tbuffer.length);
        doutpacket.setPort(out_port);
        doutpacket.setAddress(InetAddress.getByAddress(out_addr));


    }

    public UdpServer(String out_addr, int in_port, int out_port)
            throws UnknownHostException, SocketException {
        this(InetAddress.getByName(out_addr).getAddress(), in_port, out_port);
    }

    public void stopUDPThread() {
        thread_runing = false;
    }

    protected boolean valid_packet(DatagramPacket dp) {

        if (dp.getPort() != out_port) {
            return false;
        }
        if (dp.getLength() != Configurator.SHORT_LEN_MSG
                && dp.getLength() != Configurator.LONG_LEN_MSG) {
            return false;
        }

        return true;
    }

    @Override
    public void run() {
        while (thread_runing) {
            try {
                dsocket.receive(dinpacket);
                if (transmiting) {
                    if (valid_packet(dinpacket)) {
                        translateToListeners(dinpacket.getData(),
                                dinpacket.getLength());
                    }
                }
            } catch (IOException ex) {
                //комент по причине "Receive timed out" по CD
                /*StendLogger.log(StendLogger.MSG_ERROR, "Error in receive UDP"
                 + " packet. Msg: " + ex.getMessage());*/
            } catch (Exception ex) {
                StendLogger.log(StendLogger.MSG_ERROR, "Error in receive UDP"
                        + " packet. Msg: " + ex.getMessage());
            }
        }
        dsocket.close();
    }

    /**
     * Operation Отослать UDP пакет
     *
     * @param pack - массив в котором содержится пакет
     * @param len - длинна пакета в байтах
     * @return
     */
    public void sendPacket(byte[] pack, int len) throws IOException {
        doutpacket.setData(pack, 0, len);
        try {
            dsocket.send(doutpacket);
        } catch (IOException ex) {
            StendLogger.log(StendLogger.MSG_ERROR, "Can not send packet. "
                    + "IP adress: " + doutpacket.getAddress().getHostAddress()
                    + " Port: " + doutpacket.getPort()
                    + " Msg: " + ex.getMessage());
            throw ex;
        }
    }

    
}